home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / nfs / nfswatch4.0 / pktfilter.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-01  |  11.7 KB  |  498 lines

  1. #ifndef lint
  2. static char *RCSid = "$Header: /home/harbor/davy/system/nfswatch/RCS/pktfilter.c,v 4.0 1993/03/01 19:59:00 davy Exp $";
  3. #endif
  4.  
  5. #include "os.h"
  6.  
  7. /*
  8.  * pktfilter.c - filters to count the packets.
  9.  *
  10.  * David A. Curry                Jeffrey C. Mogul
  11.  * Purdue University                Digital Equipment Corporation
  12.  * Engineering Computer Network            Western Research Laboratory
  13.  * 1285 Electrical Engineering Building        250 University Avenue
  14.  * West Lafayette, IN 47907-1285        Palo Alto, CA 94301
  15.  * davy@ecn.purdue.edu                mogul@decwrl.dec.com
  16.  *
  17.  * $Log: pktfilter.c,v $
  18.  * Revision 4.0  1993/03/01  19:59:00  davy
  19.  * NFSWATCH Version 4.0.
  20.  *
  21.  * Revision 3.7  1993/02/24  17:44:45  davy
  22.  * Added -auth mode, changes to -proc mode, -map option, -server option.
  23.  *
  24.  * Revision 3.6  1993/01/16  19:08:59  davy
  25.  * Corrected Jeff's address.
  26.  *
  27.  * Revision 3.5  1993/01/15  19:33:39  davy
  28.  * Miscellaneous cleanups.
  29.  *
  30.  * Revision 3.4  1993/01/15  15:43:36  davy
  31.  * Assorted changes for porting to Solaris 2.x/SVR4.
  32.  *
  33.  * Revision 3.3  1993/01/13  21:25:18  davy
  34.  * Assorted IRIX porting changes.
  35.  *
  36.  * Revision 3.2  1993/01/13  20:18:17  davy
  37.  * Put in OS-specific define scheme, and merged in Tim Hudson's code for
  38.  * SGI systems (as yet untested).
  39.  *
  40.  * Revision 3.1  1992/07/24  18:47:57  mogul
  41.  * Added FDDI support
  42.  *
  43.  * Revision 3.0  1991/01/23  08:23:17  davy
  44.  * NFSWATCH Version 3.0.
  45.  *
  46.  * Revision 1.3  91/01/04  15:56:25  davy
  47.  * Bug fix from Jeff Mogul.
  48.  * 
  49.  * Revision 1.2  90/08/17  15:47:42  davy
  50.  * NFSWATCH Version 2.0.
  51.  * 
  52.  * Revision 1.1  88/11/29  11:20:49  davy
  53.  * NFSWATCH Release 1.0
  54.  * 
  55.  */
  56. #include <sys/param.h>
  57. #include <sys/socket.h>
  58. #include <net/if.h>
  59. #ifndef ultrix
  60. #include <net/if_arp.h>
  61. #endif
  62. #include <netinet/in.h>
  63. #include <netinet/if_ether.h>
  64. #include <netinet/in_systm.h>
  65. #include <netinet/ip.h>
  66. #include <netinet/udp.h>
  67. #include <netinet/tcp.h>
  68. #include <netinet/ip_var.h>
  69. #include <netinet/ip_icmp.h>
  70. #include <netinet/udp_var.h>
  71. #include <errno.h>
  72. #include <stdio.h>
  73.  
  74. #include "nfswatch.h"
  75. #include "externs.h"
  76. #include "screen.h"
  77.  
  78. #ifdef SUNOS4
  79. #define NND    1
  80. #include <sun/ndio.h>
  81. #endif
  82.  
  83. #ifdef ultrix
  84. #include "ultrix.map.h"
  85. #include "ipports.h"
  86. #endif
  87.  
  88. #ifdef sgi
  89. #include <rpc/types.h>
  90. #include "sgi.map.h"
  91. #include "ipports.h"
  92. #endif
  93.  
  94. /*
  95.  * Ethernet broadcast address.
  96.  */
  97. static    struct ether_addr ether_broadcast = {
  98.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  99. };
  100.  
  101. void pkt_dispatch();
  102.  
  103. /*
  104.  * pkt_filter_ether - Parse Ethernet header,
  105.  *            pass rest of packet to pkt_dispatch()
  106.  */
  107. void
  108. pkt_filter_ether(cp, length, tstamp)
  109. struct timeval *tstamp;
  110. u_int length;
  111. char *cp;
  112. {
  113.     int packet[PACKETSIZE];
  114.     register int bdcst;
  115.     struct ether_header eheader;
  116.  
  117.     /*
  118.      * Extract the ethernet header.
  119.      */
  120.     (void) bcopy(cp, (char *) &eheader, sizeof(struct ether_header));
  121.     (void) bcopy(cp + sizeof(struct ether_header), (char *) packet,
  122.         (int) (length - sizeof(struct ether_header)));
  123.  
  124.     /*
  125.      * See if it's a broadcast packet.
  126.      */
  127. #if defined(ultrix) || defined(sgi)
  128.     bdcst = !bcmp((char *) eheader.ether_dhost, (char *) ðer_broadcast,
  129.             sizeof(struct ether_addr));
  130. #else
  131.     bdcst = !bcmp((char *) &eheader.ether_dhost, (char *) ðer_broadcast,
  132.             sizeof(struct ether_addr));
  133. #endif
  134.  
  135.     /*
  136.      * Figure out what kind of packet it is, and pass
  137.      * it off to the appropriate filter.
  138.      */
  139.     pkt_dispatch(packet, length, bdcst, eheader.ether_type, tstamp);
  140. }
  141.  
  142. #ifndef    LLC_SNAP_LSAP
  143. #define LLC_UI        0x3
  144. #define LLC_SNAP_LSAP    0xaa
  145. #endif
  146.  
  147. /*
  148.  * pkt_filter_fddi - Parse FDDI and LLC headers,
  149.  *            pass rest of packet to pkt_dispatch()
  150.  */
  151. void
  152. pkt_filter_fddi(cp, length, tstamp)
  153. struct timeval *tstamp;
  154. u_int length;
  155. char *cp;
  156. {
  157.     int packet[PACKETSIZE];
  158.     register int bdcst;
  159.     struct fddi_header {
  160.             u_char    fddi_fc;
  161.             u_char    fddi_dhost[6];
  162.             u_char    fddi_shost[6];
  163.     } fheader;
  164.     struct llc_header {
  165.         u_char    llc_dsap;
  166.         u_char    llc_ssap;
  167.         u_char    llc_control;
  168.         u_char    llc_org_code[3];
  169.         u_short    llc_ether_type;
  170.     } lheader;
  171.     u_short etype;
  172.  
  173. #define    FDDI_LLC_LEN (sizeof(struct fddi_header) + sizeof(struct llc_header))
  174.  
  175.     if (length <= FDDI_LLC_LEN)
  176.         return;    /* runt */
  177.  
  178.     /*
  179.      * Extract the FDDI and LLC headers.
  180.      */
  181.     (void) bcopy(cp, (char *) &fheader, sizeof(struct fddi_header));
  182.     (void) bcopy(cp + sizeof(struct fddi_header), (char *) &lheader,
  183.             sizeof(struct llc_header));
  184.     (void) bcopy(cp + FDDI_LLC_LEN, (char *) packet,
  185.             (int) (length - FDDI_LLC_LEN));
  186.  
  187.     /* Should check FDDI frame control ... */
  188.  
  189.     /*
  190.      * See if it's a broadcast packet.
  191.      */
  192.     bdcst = !bcmp((char *) fheader.fddi_dhost, (char *) ðer_broadcast,
  193.             sizeof(struct ether_addr));
  194.  
  195.     /*
  196.      * Check LLC encapsulation type, extract Ethernet type if SNAP
  197.      */
  198.     if ((lheader.llc_dsap == LLC_SNAP_LSAP)
  199.         && (lheader.llc_ssap == LLC_SNAP_LSAP)
  200.         && (lheader.llc_control == LLC_UI)
  201.         && (lheader.llc_org_code[0] == 0)
  202.         && (lheader.llc_org_code[1] == 0)
  203.         && (lheader.llc_org_code[2] == 0)) {
  204.         etype = lheader.llc_ether_type;
  205.     }
  206.     else
  207.         etype = 0;
  208.  
  209.     /*
  210.      * Figure out what kind of packet it is, and pass
  211.      * it off to the appropriate filter.
  212.      */
  213.     pkt_dispatch(packet, length, bdcst, etype, tstamp);
  214. }
  215.  
  216. /*
  217.  * pkt_dispatch - count a packet, and pass it off to the appropriate filter.
  218.  *        Caller tells us the Ethernet type code and if the packet
  219.  *        was a broadcast.
  220.  */
  221. void
  222. pkt_dispatch(packet, length, bdcst, etype, tstamp)
  223. struct timeval *tstamp;
  224. int *packet;            /* address of IP or ARP header */
  225. u_int length;
  226. int bdcst;            /* was packet a LAN broadcast? */
  227. u_short etype;            /* still in network byte-order */
  228. {
  229.     struct ip *ip;
  230.     struct ether_arp *arp;
  231.     register int want;
  232.  
  233.     /*
  234.      * Count this packet in the network totals.
  235.      */
  236.     int_pkt_total++;
  237.     pkt_total++;
  238.  
  239.     /*
  240.      * See if it's a broadcast packet, and count it if it is.
  241.      */
  242.     if (bdcst) {
  243.         pkt_counters[PKT_BROADCAST].pc_interval++;
  244.         pkt_counters[PKT_BROADCAST].pc_total++;
  245.     }
  246.  
  247.     /*
  248.      * Figure out what kind of packet it is, and pass
  249.      * it off to the appropriate filter.
  250.      */
  251.     switch (ntohs(etype)) {
  252.     case ETHERTYPE_IP:        /* IP packet            */
  253.         ip = (struct ip *) packet;
  254.         want = want_packet(ip->ip_src.s_addr, ip->ip_dst.s_addr);
  255.  
  256.         /*
  257.          * If we want this packet, count it in the host
  258.          * totals and pass it off.
  259.          */
  260.         if (bdcst || want) {
  261.             int_dst_pkt_total++;
  262.             dst_pkt_total++;
  263.  
  264.             ip_filter(ip, length, ip->ip_src.s_addr,
  265.                 ip->ip_dst.s_addr, tstamp);
  266.         }
  267.  
  268.         break;
  269.     case ETHERTYPE_ARP:        /* Address Resolution Protocol    */
  270.         arp = (struct ether_arp *) packet;
  271.         want = want_packet(arp->arp_spa, arp->arp_tpa);
  272.  
  273.         /*
  274.          * If we want this packet, count it in the host
  275.          * totals and then count it in the packet
  276.          * type counters.
  277.          */
  278.         if (bdcst || want) {
  279.             int_dst_pkt_total++;
  280.             dst_pkt_total++;
  281.  
  282.             pkt_counters[PKT_ARP].pc_interval++;
  283.             pkt_counters[PKT_ARP].pc_total++;
  284.         }
  285.  
  286.         break;
  287.     case ETHERTYPE_REVARP:        /* Reverse Addr Resol Protocol    */
  288.         arp = (struct ether_arp *) packet;
  289.         want = want_packet(arp->arp_spa, arp->arp_tpa);
  290.  
  291.         /*
  292.          * If we want this packet, count it in the host
  293.          * totals and then count it in the packet
  294.          * type counters.
  295.          */
  296.         if (bdcst || want) {
  297.             int_dst_pkt_total++;
  298.             dst_pkt_total++;
  299.  
  300.             pkt_counters[PKT_RARP].pc_interval++;
  301.             pkt_counters[PKT_RARP].pc_total++;
  302.         }
  303.  
  304.         break;
  305. #ifdef notdef
  306.     case ETHERTYPE_PUP:        /* Xerox PUP            */
  307. #endif
  308.     default:            /* who knows...            */
  309.         int_dst_pkt_total++;
  310.         dst_pkt_total++;
  311.  
  312.         pkt_counters[PKT_OTHER].pc_interval++;
  313.         pkt_counters[PKT_OTHER].pc_total++;
  314.         break;
  315.     }
  316. }
  317.  
  318. /*
  319.  * ip_filter - strip off the IP header and pass off to the appropriate
  320.  *           filter.
  321.  */
  322. void
  323. ip_filter(ip, length, src, dst, tstamp)
  324. struct timeval *tstamp;
  325. register struct ip *ip;
  326. u_long src, dst;
  327. u_int length;
  328. {
  329.     register int *data;
  330.     register int datalength;
  331.  
  332.     data = (int *) ip;
  333.     data += ip->ip_hl;
  334.     datalength = ntohs(ip->ip_len) - (4 * ip->ip_hl);
  335.  
  336.     /*
  337.      * Figure out what kind of IP packet this is, and
  338.      * pass it off to the appropriate filter.
  339.      */
  340.     switch (ip->ip_p) {
  341.     case IPPROTO_TCP:        /* transmission control protocol*/
  342.         tcp_filter((struct tcphdr *) data, datalength,
  343.             src, dst, tstamp);
  344.         break;
  345.     case IPPROTO_UDP:        /* user datagram protocol    */
  346.         udp_filter((struct udphdr *) data, datalength,
  347.             src, dst, tstamp);
  348.         break;
  349.     case IPPROTO_ND:        /* Sun Network Disk protocol    */
  350.         nd_filter((char *) data, datalength, src, dst, tstamp);
  351.         break;
  352.     case IPPROTO_ICMP:        /* control message protocol    */
  353.         icmp_filter((struct icmp *) data, datalength,
  354.             src, dst, tstamp);
  355.         break;
  356. #ifdef notdef
  357.     case IPPROTO_IGMP:        /* group message protocol    */
  358.     case IPPROTO_GGP:        /* gateway-gateway protocol    */
  359.     case IPPROTO_EGP:        /* exterior gateway protocol    */
  360.     case IPPROTO_PUP:        /* Xerox pup protocol        */
  361.     case IPPROTO_IDP:        /* XNS IDP            */
  362. #endif
  363.     default:            /* who knows...            */
  364.         break;
  365.     }
  366. }
  367.  
  368. /*
  369.  * tcp_filter - count TCP packets.
  370.  */
  371. void
  372. tcp_filter(tcp, length, src, dst, tstamp)
  373. register struct tcphdr *tcp;
  374. struct timeval *tstamp;
  375. u_long src, dst;
  376. u_int length;
  377. {
  378.     /*
  379.      * Just count the packet.
  380.      */
  381.     pkt_counters[PKT_TCP].pc_interval++;
  382.     pkt_counters[PKT_TCP].pc_total++;
  383. }
  384.  
  385. /*
  386.  * udp_filter - count UDP packets, pass RPC packets to the RPC filter.
  387.  */
  388. void
  389. udp_filter(udp, length, src, dst, tstamp)
  390. register struct udphdr *udp;
  391. struct timeval *tstamp;
  392. u_long src, dst;
  393. u_int length;
  394. {
  395.     /*
  396.      * Count as a UDP packet.
  397.      */
  398.     pkt_counters[PKT_UDP].pc_interval++;
  399.     pkt_counters[PKT_UDP].pc_total++;
  400.  
  401.     /*
  402.      * See what type of packet it is.  Pass off
  403.      * anything we don't recognize to the RPC
  404.      * filter.
  405.      */
  406.     switch (ntohs(udp->uh_sport)) {
  407.     case IPPORT_ROUTESERVER:    /* routing control protocol    */
  408.         pkt_counters[PKT_ROUTING].pc_interval++;
  409.         pkt_counters[PKT_ROUTING].pc_total++;
  410.         break;
  411. #ifdef notdef
  412.                     /* network standard functions    */
  413.     case IPPORT_ECHO:        /* packet echo server        */
  414.     case IPPORT_DISCARD:        /* packet discard server    */
  415.     case IPPORT_SYSTAT:        /* system stats            */
  416.     case IPPORT_DAYTIME:        /* time of day server        */
  417.     case IPPORT_NETSTAT:        /* network stats        */
  418.     case IPPORT_FTP:        /* file transfer        */
  419.     case IPPORT_TELNET:        /* remote terminal service    */
  420.     case IPPORT_SMTP:        /* simple mail transfer protocol*/
  421.     case IPPORT_TIMESERVER:        /* network time synchronization    */
  422.     case IPPORT_NAMESERVER:        /* domain name lookup        */
  423.     case IPPORT_WHOIS:        /* white pages            */
  424.     case IPPORT_MTP:        /* ???                */
  425.                     /* host specific functions    */
  426.     case IPPORT_TFTP:        /* trivial file transfer    */
  427.     case IPPORT_RJE:        /* remote job entry        */
  428.     case IPPORT_FINGER:        /* finger            */
  429.     case IPPORT_TTYLINK:        /* ???                */
  430.     case IPPORT_SUPDUP:        /* SUPDUP            */
  431.                     /* UNIX TCP services        */
  432.     case IPPORT_EXECSERVER:        /* rsh                */
  433.     case IPPORT_LOGINSERVER:    /* rlogin            */
  434.     case IPPORT_CMDSERVER:        /* rcmd                */
  435.                     /* UNIX UDP services        */
  436.     /* case IPPORT_BIFFUDP:        /* biff mail notification    */
  437.     /* case IPPORT_WHOSERVER:    /* rwho                */
  438. #endif
  439.     default:            /* might be an RPC packet    */
  440.         rpc_filter((char *) udp + sizeof(struct udphdr),
  441.             ntohs(udp->uh_ulen) - sizeof(struct udphdr),
  442.             src, dst, tstamp);
  443.         break;
  444.     }
  445. }
  446.  
  447. /*
  448.  * nd_filter - count Sun ND packets.
  449.  */
  450. void
  451. nd_filter(data, length, src, dst, tstamp)
  452. struct timeval *tstamp;
  453. u_long src, dst;
  454. u_int length;
  455. char *data;
  456. {
  457. #ifdef SUNOS4
  458.     register struct ndpack *nd;
  459.  
  460.     nd = (struct ndpack *) (data - sizeof(struct ip));
  461.  
  462.     /*
  463.      * Figure out whether it's a read or a write.
  464.      */
  465.     switch (nd->np_op & NDOPCODE) {
  466.     case NDOPREAD:
  467.         pkt_counters[PKT_NDREAD].pc_interval++;
  468.         pkt_counters[PKT_NDREAD].pc_total++;
  469.         break;
  470.     case NDOPWRITE:
  471.         pkt_counters[PKT_NDWRITE].pc_interval++;
  472.         pkt_counters[PKT_NDWRITE].pc_total++;
  473.         break;
  474.     case NDOPERROR:
  475.     default:
  476.         pkt_counters[PKT_OTHER].pc_interval++;
  477.         pkt_counters[PKT_OTHER].pc_total++;
  478.         break;
  479.     }
  480. #else /* SUNOS4 */
  481.     pkt_counters[PKT_OTHER].pc_interval++;
  482.     pkt_counters[PKT_OTHER].pc_total++;
  483. #endif /* SUNOS4 */
  484. }
  485.  
  486. /*
  487.  * icmp_filter - count ICMP packets.
  488.  */
  489. void icmp_filter(icp, length, src, dst, tstamp)
  490. register struct icmp *icp;
  491. struct timeval *tstamp;
  492. u_long src, dst;
  493. u_int length;
  494. {
  495.     pkt_counters[PKT_ICMP].pc_interval++;
  496.     pkt_counters[PKT_ICMP].pc_total++;
  497. }
  498.